Skip to content

Java: CAM v1.1.3 refactoring and new CAM v2.3.0#489

Merged
mathieu1fb merged 31 commits intoOrange-OpenSource:masterfrom
mathieu1fb:cam-refactoring
Mar 10, 2026
Merged

Java: CAM v1.1.3 refactoring and new CAM v2.3.0#489
mathieu1fb merged 31 commits intoOrange-OpenSource:masterfrom
mathieu1fb:cam-refactoring

Conversation

@mathieu1fb
Copy link
Collaborator

@mathieu1fb mathieu1fb commented Mar 9, 2026

What's new

  • CAM v2.3.0 support has been added
  • CAM v1.1.3 has been refactored completely for compatibility, so that both versions can be handled in parallel

Close #485
Close #486


What to do

After reviewing code changes:

  1. Clone the its-client project on your IDE.
  2. Ensure that you have Gradle to be able to build the java/iot3 modules (core, mobility and examples).
  3. Find the Iot3MobilityExample class in the examples module, and set appropriate values for the following fields:
private static final String EXAMPLE_UUID = "uuid";
private static final String EXAMPLE_CONTEXT = "context";
// MQTT parameters
private static final String EXAMPLE_MQTT_HOST = "mqtt_host";
private static final int EXAMPLE_MQTT_PORT = 1883;
private static final String EXAMPLE_MQTT_USERNAME = "mqtt_username";
private static final String EXAMPLE_MQTT_PASSWORD = "mqtt_password";
private static final boolean EXAMPLE_MQTT_USE_TLS = true; // set to true
  1. In the same class, remove the telemetry and LwM2M parameters from the IoT3Mobility builder as they won't be used:
.telemetryParams(EXAMPLE_OTL_SCHEME,
                        EXAMPLE_OTL_HOST,
                        EXAMPLE_OTL_PORT,
                        EXAMPLE_OTL_ENDPOINT,
                        EXAMPLE_OTL_USERNAME,
                        EXAMPLE_OTL_PASSWORD)
.lwm2mParams(
                        EXAMPLE_LWM2M_CONFIG,
                        EXAMPLE_LWM2M_DEVICE,
                        lwm2mConnectivityStatistics)
  1. Run Iot3MobilityExample for a few seconds.
  2. Stop it.
  3. Modify the CamVersion.V1_1_3 parameter in the ioT3Mobility.sendPosition(...) method by CamVersion.V2_3_0.
  4. Run Iot3MobilityExample for a few seconds.
  5. Stop it.

Expected results

  1. During the first run, you should see CAMs v1.1.3 being received and processed (i.e. turned into RoadUser objects).
Raw message received: {"type":"cam","origin":"self","version":"1.1.3","source_uuid":"ora_test_123","timestamp":1773072528767,"message":{"protocol_version":2,"station_id":78486518,"generation_delta_time":64895,"basic_container":{"station_type":5,"reference_position":{"latitude":486252180,"longitude":22434480,"altitude":0}},"high_frequency_container":{"heading":0,"speed":0,"longitudinal_acceleration":0,"yaw_rate":0}}}

Raw CAM v1.1.3: CamEnvelope113[type=cam, origin=self, version=1.1.3, sourceUuid=ora_test_123, timestamp=1773072528767, message=CamMessage113[protocolVersion=2, stationId=78486518, generationDeltaTime=64895, basicContainer=BasicContainer[stationType=5, referencePosition=ReferencePosition[latitude=486252180, longitude=22434480, altitude=0], confidence=null], highFrequencyContainer=HighFrequencyContainer[heading=0, speed=0, driveDirection=null, vehicleLength=null, vehicleWidth=null, curvature=null, curvatureCalculationMode=null, longitudinalAcceleration=0, yawRate=0, accelerationControl=null, lanePosition=null, lateralAcceleration=null, verticalAcceleration=null, confidence=null], lowFrequencyContainer=null]]
New Road User: ora_test_123_78486518
Road User position: lat/lng: (48.625218,2.243448)
  1. During the second run, you should see the exact same with CAMs v2.3.0.
Raw message received: {"message_type":"cam","message_format":"json/raw","source_uuid":"ora_test_123","timestamp":1773070072412,"version":"2.3.0","message":{"protocol_version":2,"station_id":24793671,"generation_delta_time":33372,"basic_container":{"station_type":5,"reference_position":{"latitude":486252180,"longitude":22434480,"position_confidence_ellipse":{"semi_major":10,"semi_minor":10,"semi_major_orientation":0},"altitude":{"value":0,"confidence":15}}},"high_frequency_container":{"basic_vehicle_container_high_frequency":{"heading":{"value":0,"confidence":127},"speed":{"value":0,"confidence":127},"drive_direction":2,"vehicle_length":{"value":1023,"confidence":4},"vehicle_width":62,"longitudinal_acceleration":{"value":0,"confidence":102},"curvature":{"value":1023,"confidence":7},"curvature_calculation_mode":2,"yaw_rate":{"value":0,"confidence":8}}}}}

Raw CAM v2.3.0: CamEnvelope230[messageType=cam, messageFormat=json/raw, sourceUuid=ora_test_123, timestamp=1773070072412, version=2.3.0, message=CamStructuredData[protocolVersion=2, stationId=24793671, generationDeltaTime=33372, basicContainer=BasicContainer[stationType=5, referencePosition=ReferencePosition[latitude=486252180, longitude=22434480, positionConfidenceEllipse=PositionConfidenceEllipse[semiMajor=10, semiMinor=10, semiMajorOrientation=0], altitude=Altitude[value=0, confidence=15]]], highFrequencyContainer=BasicVehicleContainerHighFrequency[heading=Heading[value=0, confidence=127], speed=Speed[value=0, confidence=127], driveDirection=2, vehicleLength=VehicleLength[value=1023, confidence=4], vehicleWidth=62, longitudinalAcceleration=AccelerationComponent[value=0, confidence=102], curvature=Curvature[value=1023, confidence=7], curvatureCalculationMode=2, yawRate=YawRate[value=0, confidence=8], accelerationControl=null, lanePosition=null, steeringWheelAngle=null, lateralAcceleration=null, verticalAcceleration=null, performanceClass=null, cenDsrcTollingZone=null], lowFrequencyContainer=null, specialVehicleContainer=null]]
New Road User: ora_test_123_24793671
Road User position: lat/lng: (48.625218,2.243448)

Note: it is normal if source_uuid, station_id and timestamps differ in your test.

This new implementation should be faster and is clearly versioned.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…nversion

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…e simple methods

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…2.3.0 implementations

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…3 and v2.3.0 implementations

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
The user shouldn't have to set message type and version, so we set them.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…ckage

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…ehicleContainer

The SpecialVehicleContainer is actually not part of the JSON schema for this CAM version, and was anyway empty.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
… CamWriter113

This container was not part of the CAM v1.1.3 spec and has been removed.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…CamValidator230

This field was wrongly expected to be mandatory.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
…(...) method

Note that handling both CAM versions in the same class makes imports messy since many 1.1.3 and 2.3.0 classes have the same name. Maybe we should add a version suffix to each class.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Max value was erroneously set to 01-01-2028 in the JSON schema, which will break soon.

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
@mathieu1fb mathieu1fb added this to the Sprint 19 milestone Mar 9, 2026
@mathieu1fb mathieu1fb requested a review from fredOG-2A1 March 9, 2026 16:12
@mathieu1fb mathieu1fb self-assigned this Mar 9, 2026
@mathieu1fb mathieu1fb added the Java label Mar 9, 2026
Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
… Java SDK

Signed-off-by: Mathieu LEFEBVRE <mathieu1.lefebvre@orange.com>
Copy link
Member

@fredOG-2A1 fredOG-2A1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have tested with your recommandations.
It works as expected:
Raw message received: {"type":"cam","origin":"self","version":"1.1.3","source_uuid":"uuid","timestamp":1773139624269,"message":...}}
Raw CAM v1.1.3: CamEnvelope113[type=cam, origin=self, version=1.1.3, sourceUuid=uuid, timestamp=1773140392318, message=CamMessage113[protocolVersion=2, stationId=95569549, generationDeltaTime=33150, basicContainer=BasicContainer[...], highFrequencyContainer=HighFrequencyContainer[...], lowFrequencyContainer=null]]

Raw message received: {"message_type":"cam","message_format":"json/raw","source_uuid":"uuid","timestamp":1773140102589,"version":"2.3.0","message":...}}}
Raw CAM v2.3.0: CamEnvelope230[messageType=cam, messageFormat=json/raw, sourceUuid=uuid, timestamp=1773140597331, version=2.3.0, message=CamStructuredData[protocolVersion=2, stationId=28036714, generationDeltaTime=41555, basicContainer=BasicContainer[...], highFrequencyContainer=BasicVehicleContainerHighFrequency[...]]

Huge work!

Just a thought, what about using static vars to avoid this kink of writings:
"source_uuid" or others. Replacing by SOURCE_UUID that contains 'source_uuid' ensure that no mispelling could occure.
Just a suggestion.

@mathieu1fb
Copy link
Collaborator Author

Have tested with your recommandations. It works as expected: Raw message received: {"type":"cam","origin":"self","version":"1.1.3","source_uuid":"uuid","timestamp":1773139624269,"message":...}} Raw CAM v1.1.3: CamEnvelope113[type=cam, origin=self, version=1.1.3, sourceUuid=uuid, timestamp=1773140392318, message=CamMessage113[protocolVersion=2, stationId=95569549, generationDeltaTime=33150, basicContainer=BasicContainer[...], highFrequencyContainer=HighFrequencyContainer[...], lowFrequencyContainer=null]]

Raw message received: {"message_type":"cam","message_format":"json/raw","source_uuid":"uuid","timestamp":1773140102589,"version":"2.3.0","message":...}}} Raw CAM v2.3.0: CamEnvelope230[messageType=cam, messageFormat=json/raw, sourceUuid=uuid, timestamp=1773140597331, version=2.3.0, message=CamStructuredData[protocolVersion=2, stationId=28036714, generationDeltaTime=41555, basicContainer=BasicContainer[...], highFrequencyContainer=BasicVehicleContainerHighFrequency[...]]

Huge work!

Just a thought, what about using static vars to avoid this kink of writings: "source_uuid" or others. Replacing by SOURCE_UUID that contains 'source_uuid' ensure that no mispelling could occure. Just a suggestion.

Thank you for the review! I have indeed considered using some sort of dictionary for all the JSON fields, but have not done so. I might do it in a future version.

@mathieu1fb mathieu1fb merged commit 6f62840 into Orange-OpenSource:master Mar 10, 2026
115 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Refactor CAM v1.1.3 Add support for CAM v2.3.0

2 participants